home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume19 / atty / part03 < prev    next >
Encoding:
Internet Message Format  |  1989-05-30  |  50.7 KB

  1. Subject:  v19i012:  A command-line editor (for BSD), Part03/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: ka@june.cs.washington.edu (Kenneth Almquist)
  7. Posting-number: Volume 19, Issue 12
  8. Archive-name: atty/part03
  9.  
  10. # This is part 3 of atty.  To unpack, feed it into the shell (not csh).
  11. # The atty distribution consists of four pieces.  After you unpack everyting,
  12. # read the file README.
  13.  
  14. echo extracting kbind.c
  15. cat > kbind.c <<\EOF
  16. /*
  17.  * The kbind program - compile .bind files.
  18.  *
  19.  * Copyright (C) 1989 by Kenneth Almquist.  All rights reserved.
  20.  * This file is part of atty, which is distributed under the terms specified
  21.  * by the Atty General Public License.  See the file named LICENSE.
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include "bind.h"
  26.  
  27.  
  28. #define VERSION 21    /* change if you change the .bindc format */
  29.  
  30.  
  31. /*
  32.  * List of commands.
  33.  */
  34.  
  35. char *command[] = {
  36.     "universal-argument",
  37.     "digit-argument",
  38.     "negative-argument",
  39.     "self-insert",
  40.     "quoted-insert",
  41.     "newline",
  42.     "end-of-file",
  43.     "eof-or-delete-char",
  44.     "newline-and-insert",
  45.     "tty-intr",
  46.     "tty-quit",
  47.     "tty-susp",
  48.     "delete-backward-char",
  49.     "delete-char",
  50.     "kill-word",
  51.     "backward-kill-word",
  52.     "kill-region",
  53.     "kill-line",
  54.     "kill-input",
  55.     "copy-region-as-kill",
  56.     "forward-char",
  57.     "backward-char",
  58.     "forward-word",
  59.     "backward-word",
  60.     "beginning-of-line",
  61.     "end-of-line",
  62.     "yank",
  63.     "set-mark",
  64.     "exchange-point-and-mark",
  65.     "upcase-char",
  66.     "upcase-word",
  67.     "upcase-region",
  68.     "gosling-transpose-chars",
  69.     "transpose-chars",
  70.     "transpose-words",
  71.     "next-history",
  72.     "previous-history",
  73.     "beginning-of-history",
  74.     "end-of-history",
  75.     "re-search-forward",
  76.     "re-search-backward",
  77.     "file-complete",
  78.     "list-file-completions",
  79.     "get-history-word",
  80.     "last-output-line",
  81.     "mode-0",
  82.     "mode-1",
  83.     0
  84. };
  85.  
  86.  
  87.  
  88. /* Token types */
  89. #define TWORD    1    /* generic word */
  90. #define TNL    2    /* newline */
  91. #define TSTRING    3    /* quoted string */
  92.  
  93.  
  94. #define C_UNSET 127    /* command is not set */
  95.  
  96.  
  97. #define NMODES 2    /* maximum number of modes */
  98. #define TBLSIZE 128    /* size of a key table */
  99. #define MAXTBL 32    /* maximum number of key tables */
  100. #define STRINGSPACE 5000 /* space for holding strings */
  101. #define MAXABBREV 500    /* maximum number of abbreviations */
  102.  
  103.  
  104. struct cmd {
  105.       unsigned char type;    /* type of command */
  106.       unsigned char index;    /* which command */
  107.       int linno;        /* line where defined */
  108. };
  109.  
  110.  
  111. struct mode {
  112.       int used;            /* set if mode is in use */
  113.       struct cmd dft;        /* default binding */
  114.       struct cmd *keytab;    /* base key table for this mode */
  115. };
  116.  
  117.  
  118. struct syntax {
  119.       char *name;        /* name of this syntax class */
  120.       int defined;        /* set if syntax defined */
  121.       char bitmap[16];        /* bit map specifying which characters are
  122.                    in the class */
  123. };
  124.  
  125.  
  126. struct abbrev {
  127.       int fromlen;        /* length of "from" */
  128.       char *from;        /* the abbreviation */
  129.       int tolen;        /* length of "to" */
  130.       char *to;            /* what it is defined as */
  131. };
  132.  
  133.  
  134. char *inputfile;        /* name of input file */
  135. FILE *infp;            /* input file */
  136. char outputfile[1024];        /* name of output file */
  137. FILE *outfp;            /* output file */
  138. struct mode mode[NMODES];    /* modes */
  139. struct mode *curmode;        /* current mode */
  140. int nmodes;            /* number of modes actually used */
  141. struct cmd *keytab[MAXTBL];    /* key binding tables */
  142. int nkeytab;            /* number of key tables */
  143. struct syntax syntax[NSYNTAX];    /* syntax tables */
  144. char stringspace[STRINGSPACE];    /* space for holding strings */
  145. char *strnext;            /* next entry in string table */
  146. int nstrings;            /* number of strings in string table */
  147. int nabbrev;            /* number of abbreviations */
  148. struct abbrev abbrev[MAXABBREV];/* abbreviations */
  149. int abbrevsize;            /* total size of abbreviation table */
  150. int mode_1_line;        /* line that mode-1 command occured on */
  151. int lasttoken;            /* type of last token read */
  152. int tokpushback;        /* set to push back token */
  153. char toktext[1024];        /* text of last token read */
  154. char tokstring[512];        /* input string */
  155. char stringlen;            /* length of tokstring */
  156. int linno;            /* current line of input */
  157. int nerrors;            /* number of errors encountered */
  158. int debug;            /* set for debugging info */
  159.  
  160.  
  161. #ifdef __STDC__
  162. void makefuncs(void);
  163. char *cname(char *);
  164. void parsefile(void);
  165. void parseline(void);
  166. void parsecmd(struct cmd *);
  167. void setmode(int);
  168. void bind(char *, int, struct cmd *);
  169. struct cmd *newkeytab(void);
  170. void defaultbind(void);
  171. void setdftbind(struct cmd *, struct cmd *);
  172. void setsyntax(char *, char *, int);
  173. void chknl(void);
  174. int gettoken(void);
  175. int getstring(void);
  176. void cvttext(int);
  177. int ateof(void);
  178. char *saveblock(char *, int);
  179. void error(char *);
  180. int writeout(void);
  181. void putkeytab(struct cmd *);
  182. void putsh(int, FILE *);
  183. #else
  184. void makefuncs();
  185. char *cname();
  186. void parsefile();
  187. void parseline();
  188. void parsecmd();
  189. void setmode();
  190. void bind();
  191. struct cmd *newkeytab();
  192. void defaultbind();
  193. void setdftbind();
  194. void setsyntax();
  195. void chknl();
  196. int gettoken();
  197. int getstring();
  198. void cvttext();
  199. int ateof();
  200. char *saveblock();
  201. void error();
  202. int writeout();
  203. void putkeytab();
  204. void putsh();
  205. #endif
  206.  
  207. char *malloc();
  208. #define equal(s1, s2)    (strcmp(s1, s2) == 0)
  209.  
  210.  
  211.  
  212. main(argc, argv)
  213.       char **argv;
  214.       {
  215.       char **ap;
  216.       int status;
  217.  
  218.       if (argc <= 1) {
  219.         fputs("Usage:  kbind file.bind ...\n", stderr);
  220.         exit(2);
  221.       }
  222.       if (argc == 2 && equal(argv[1], "-makefuncs")) {
  223.         makefuncs();
  224.         return 0;
  225.       }
  226.       if (equal(argv[1], "-d")) {
  227.         argv++;
  228.         debug = 1;
  229.       }
  230.       status = 0;
  231.       for (ap = argv + 1 ; *ap ; ap++) {
  232.         inputfile = *ap;
  233.         if ((infp = fopen(inputfile, "r")) == NULL) {
  234.           fprintf(stderr, "Can't open %s\n", inputfile);
  235.           status = 2;
  236.         }
  237.         nerrors = 0;
  238.         parsefile();
  239.         if (nerrors != 0) {
  240.           if (status == 0)
  241.             status = 1;
  242.           continue;
  243.         }
  244.         if (writeout() < 0)
  245.           status = 2;
  246.       }
  247.       exit(status);
  248. }
  249.  
  250.  
  251. /*
  252.  * Generate function index to be compiled with atty.
  253.  */
  254.  
  255. char head[] = "\
  256. /*\n\
  257.  * This file was created by the kbind program.\n\
  258.  */\n\
  259. \n";
  260.  
  261. void
  262. makefuncs() {
  263.       char **pp;
  264.  
  265.       if ((outfp = fopen("edfuncs.c", "w")) == NULL) {
  266.         fputs("Can't create edfuncs.c\n", stderr);
  267.         exit(2);
  268.       }
  269.       fputs(head, outfp);
  270.       for (pp = command ; *pp ; pp++) {
  271.         fprintf(outfp, "int %s();\n", cname(*pp));
  272.       }
  273.       putc('\n', outfp);
  274.       fputs("int (*edfunc[])() = {\n", outfp);
  275.       for (pp = command ; *pp ; pp++) {
  276.         fprintf(outfp, "      %s,\n", cname(*pp));
  277.       }
  278.       fputs("};\n\n", outfp);
  279.       fprintf(outfp, "int version = %d;\n", VERSION);
  280. }
  281.  
  282.  
  283. /*
  284.  * Convert a function name to the way that it appears in C.
  285.  */
  286.  
  287. char *
  288. cname(s)
  289.       char *s;
  290.       {
  291.       static char buf[128];
  292.       char *p;
  293.  
  294.       strcpy(buf, s);
  295.       for (p = buf ; *p ; p++) {
  296.         if (*p == '-')
  297.           *p = '_';
  298.       }
  299.       return buf;
  300. }
  301.  
  302.  
  303. void
  304. parsefile() {
  305.       int i;
  306.  
  307.       linno = 1;
  308.       curmode = NULL;
  309.       nkeytab = 0;
  310.       nmodes = 0;
  311.       strnext = stringspace;
  312.       nstrings = 0;
  313.       nabbrev = 0;
  314.       syntax[0].name = "word";
  315.       syntax[0].defined = 0;
  316.       syntax[1].name = "filename";
  317.       syntax[1].defined = 0;
  318.       syntax[2].name = "abbrev";
  319.       syntax[2].defined = 0;
  320.       for (i = 0 ; i < NMODES ; i++) {
  321.         mode[i].used = 0;
  322.         mode[i].dft.type = C_UNSET;
  323.         mode[i]. keytab = NULL;
  324.       }
  325.  
  326.       while (! ateof()) {
  327.         parseline();
  328.       }
  329.       for (i = 0 ; i < NSYNTAX ; i++) {
  330.         if (! syntax[i].defined)
  331.           setsyntax(syntax[i].bitmap, "^ \t", 3);
  332.       }
  333.       if (curmode == NULL) {
  334.         printf("%s:%d: No bindings specified\n", inputfile, linno);
  335.         nerrors++;
  336.       } else if (mode[0].used == 0) {
  337.         printf("%s:%d: Mode zero not defined\n", inputfile, linno);
  338.         nerrors++;
  339.       }
  340.       if (mode_1_line != 0 && mode[1].used == 0) {
  341.         printf("%s:%d: Mode 1 referenced (line %d), but never defined\n",
  342.            inputfile, linno, mode_1_line);
  343.         nerrors++;
  344.       }
  345.       nmodes = 1;
  346.       for (i = 1 ; i < NMODES ; i++) {
  347.         if (mode[i].used) {
  348.           if (! mode[i - 1].used) {
  349.             printf("%s:%d: Mode %d is defined, but mode %d is not\n",
  350.                   inputfile, linno, i, i - 1);
  351.             nerrors++;
  352.           }
  353.           nmodes = i + 1;
  354.         }
  355.       }
  356.       defaultbind();
  357.       abbrevsize = 0;
  358.       for (i = 0 ; i < nabbrev ; i++) {
  359.         abbrevsize += abbrev[i].fromlen + abbrev[i].tolen + 2;
  360.       }
  361. }
  362.  
  363.  
  364.  
  365. void
  366. parseline() {
  367.       struct cmd cmd;
  368.       char binding[128];
  369.       int bindlen;
  370.       int i;
  371.  
  372.       if (gettoken() == TNL)
  373.         goto out;
  374.       if (lasttoken != TWORD) {
  375.         error("Expecting command");
  376.         goto out;
  377.       }
  378.       if (toktext[0] == '#') {
  379.         /* a comment, ignore it */
  380.       } else if (equal(toktext, "b")) {
  381.         if (curmode == NULL) {
  382.           error("No mode specified");
  383.           setmode(0);
  384.         }
  385.         if (gettoken() != TWORD) {
  386.           error("Expecting key sequence for b command");
  387.           goto out;
  388.         }
  389.         cvttext(1);        /* parse and save value */
  390.         bindlen = stringlen;
  391.         bcopy(tokstring, binding, bindlen);
  392.         parsecmd(&cmd);
  393.         bind(binding, bindlen, &cmd);
  394.         chknl();
  395.       } else if (equal(toktext, "mode")) {
  396.         if (gettoken() != TWORD || *toktext < '0'
  397.          || *toktext > '9' || toktext[1] != '\0') {
  398.           error("Expecting mode number");
  399.           goto out;
  400.         }
  401.         setmode(atoi(toktext));
  402.         chknl();
  403.       } else if (equal(toktext, "default")) {
  404.         if (curmode == NULL) {
  405.           error("No mode specified");
  406.           setmode(0);
  407.         }
  408.         parsecmd(&cmd);
  409.         curmode->dft = cmd;
  410.         chknl();
  411.       } else if (equal(toktext, "syntax")) {
  412.         if (gettoken() != TWORD) {
  413.           error("Expecting syntax class name");
  414.           goto out;
  415.         }
  416.         for (i = 0 ; ; i++) {
  417.           if (equal(toktext, syntax[i].name))
  418.             break;
  419.           if (i == NSYNTAX - 1)
  420.             error("Unimplemented syntax class");
  421.         }
  422.         if (syntax[i].defined)
  423.           error("Redefining syntax class");
  424.         if (getstring() < 0)
  425.           goto out;
  426.         cvttext(0);
  427.         setsyntax(syntax[i].bitmap, tokstring, stringlen);
  428.         syntax[i].defined = 1;
  429.         chknl();
  430.       } else if (equal(toktext, "abbrev")) {
  431.         if (nabbrev >= MAXABBREV) {
  432.           error("Too many abbreviations");
  433.           nabbrev = 0;
  434.         }
  435.         if (getstring() < 0)
  436.           goto out;
  437.         cvttext(0);
  438.         if (stringlen == 0)
  439.           error("Can't define the null string to be an abbreviation");
  440.         abbrev[nabbrev].fromlen = stringlen;
  441.         abbrev[nabbrev].from = saveblock(tokstring, stringlen);
  442.         if (getstring() < 0)
  443.           goto out;
  444.         cvttext(0);
  445.         abbrev[nabbrev].tolen = stringlen;
  446.         abbrev[nabbrev].to = saveblock(tokstring, stringlen);
  447.         nabbrev++;
  448.         chknl();
  449.       } else {
  450.         error("Unrecognized command");
  451.       }
  452. out:
  453.       while (lasttoken != TNL)
  454.         gettoken();
  455. }
  456.  
  457.  
  458. void
  459. parsecmd(cmdp)
  460.       struct cmd *cmdp;
  461.       {
  462.       char **pp;
  463.  
  464.       cmdp->type = C_UNDEF;
  465.       cmdp->linno = linno;
  466.       if (gettoken() != TWORD) {
  467.         error("Expecting function name");    
  468.         return;
  469.       }
  470.       if (equal(toktext, "insert")) {
  471.         if (getstring() < 0)
  472.           return;
  473.         if (nstrings >= 255) {
  474.           error("Too many strings");
  475.           return;
  476.         }
  477.         cvttext(0);
  478.         if ((strnext - stringspace) + 1 + stringlen > STRINGSPACE) {
  479.           error("Out of space for string constants");
  480.           return;
  481.         }
  482.         *strnext++ = stringlen;
  483.         bcopy(tokstring, strnext, stringlen);
  484.         strnext += stringlen;
  485.         cmdp->type = C_INSERT;
  486.         cmdp->index = nstrings++;
  487.       } else if (equal(toktext, "undefined")) {
  488.         cmdp->type = C_UNDEF;
  489.         cmdp->index = 0;
  490.       } else {
  491.         for (pp = command ; *pp && ! equal(*pp, toktext) ; pp++);
  492.         if (*pp == NULL) {
  493.           error("Unrecognized function");
  494.           return;
  495.         }
  496.         if (equal(toktext, "mode-1"))
  497.           mode_1_line = linno;
  498.         cmdp->type = C_FUNC;
  499.         cmdp->index = pp - command;
  500.       }
  501. }
  502.  
  503.  
  504. void
  505. setmode(modenum) {
  506.       if (modenum < 0 || modenum >= NMODES) {
  507.         error("Mode number out of range");
  508.         return;
  509.       }
  510.       curmode = &mode[modenum];
  511.       curmode->used = 1;
  512.       if (curmode->keytab == NULL)
  513.         curmode->keytab = newkeytab();
  514. }
  515.  
  516.  
  517. void
  518. bind(keyseq, seqlen, cmdp)
  519.       char *keyseq;
  520.       int seqlen;
  521.       struct cmd *cmdp;
  522.       {
  523.       struct cmd *k;
  524.       struct cmd *cp;
  525.       char *p;
  526.       int lno;
  527.  
  528.       if (seqlen == 0) {            /* can't happen */
  529.         error("Empty binding sequence");
  530.         return;
  531.       }
  532.       if (curmode == NULL) {            /* can't happen */
  533.         error("No current mode");
  534.         setmode(0);
  535.       }
  536.       k = curmode->keytab;
  537.       p = keyseq;
  538.       while (--seqlen > 0) {
  539.         cp = &k[*p++ & 0177];
  540.         if (cp->type == C_UNSET) {
  541.           if (nkeytab >= MAXTBL) {
  542.             error("Too many key tables required");
  543.             return;
  544.           }
  545.           keytab[nkeytab++] = k = newkeytab();;
  546.           cp->type = C_PFXTBL;
  547.           cp->index = nkeytab - 1;
  548.           cp->linno = cmdp->linno;
  549.         } else if (cp->type == C_PFXTBL) {
  550.           k = keytab[cp->index];
  551.         } else {
  552.           goto redef;
  553.         }
  554.       }
  555.       cp = &k[*p & 0177];
  556.       if (cp->type != C_UNSET) {
  557. redef:
  558.         printf("%s:%d: Redefining key.  (Initial definition line %d)\n",
  559.            inputfile, cmdp->linno, cp->linno);
  560.         nerrors++;
  561.         return;
  562.       }
  563.       *cp = *cmdp;
  564. }
  565.  
  566.  
  567. /*
  568.  * Create a new key table.
  569.  */
  570.  
  571. struct cmd *
  572. newkeytab() {
  573.       struct cmd *keytab;
  574.       struct cmd *p;
  575.  
  576.       if ((keytab = (struct cmd *)malloc(TBLSIZE * sizeof *keytab)) == NULL) {
  577.         error("Out of space");
  578.         exit(2);
  579.       }
  580.       p = keytab + TBLSIZE;
  581.       do {
  582.         (--p)->type = C_UNSET;
  583.       } while (p > keytab);
  584.       return keytab;
  585. }
  586.  
  587.  
  588. /*
  589.  * Set the default bindings.
  590.  */
  591.  
  592. void
  593. defaultbind() {
  594.       int tabno;
  595.       struct cmd *cp;
  596.       int i;
  597.       static struct cmd dft = {C_UNDEF, 0, 0};
  598.  
  599.       for (tabno = 0 ; tabno < nmodes ; tabno++) {
  600.         if (mode[tabno].dft.type == C_UNSET)
  601.           setdftbind(mode[tabno].keytab, &dft);
  602.         else
  603.           setdftbind(mode[tabno].keytab, &mode[tabno].dft);
  604.       }
  605.       for (tabno = 0 ; tabno < nkeytab ; tabno++) {
  606.         setdftbind(keytab[tabno], &dft);
  607.       }
  608. }
  609.  
  610.  
  611.  
  612. void
  613. setdftbind(tab, dft)
  614.       struct cmd *tab;
  615.       struct cmd *dft;
  616.       {
  617.       struct cmd *cp;
  618.       int i;
  619.  
  620.       for (i = 128, cp = tab ; --i >= 0 ; cp++) {
  621.         if (cp->type == C_UNSET)
  622.           *cp = *dft;
  623.       }
  624. }
  625.  
  626.  
  627.  
  628. /*
  629.  * Set up a syntax table.
  630.  */
  631.  
  632. void
  633. setsyntax(table, string, len)
  634.       char table[16];
  635.       char *string;
  636.       {
  637.       register char *p;
  638.       int c;
  639.       int invert;
  640.  
  641.       for (p = table ; p < table + 16 ; p++)
  642.         *p = 0;
  643.       p = string;
  644.       invert = 0;
  645.       if (len > 0 && *p == '^') {
  646.         len--;
  647.         p++;
  648.         invert++;
  649.       }
  650.       while (--len >= 0) {
  651.         if (len >= 2 && p[1] == '-') {
  652.           for (c = p[0] ; c <= p[2] ; c++) {
  653.             table[(c & 0177) >> 3] |= 1 << (c & 07);
  654.           }
  655.           p += 3;
  656.           len -= 2;
  657.         } else {
  658.           c = *p++;
  659.           table[(c & 0177) >> 3] |= 1 << (c & 07);
  660.         }
  661.       }
  662.       if (invert) {
  663.         for (p = table ; p < table + 16 ; p++)
  664.           *p = ~*p;
  665.       }
  666. }
  667.  
  668.  
  669. /*
  670.  * Be sure the next token is a newline.
  671.  */
  672.  
  673. void
  674. chknl() {
  675.       if (gettoken() != TNL)
  676.         error("Expecting NEWLINE");
  677. }
  678.  
  679.  
  680. /*
  681.  * Return the next input token.
  682.  */
  683.  
  684. int
  685. gettoken() {
  686.       int c;
  687.       char *p;
  688.  
  689.       if (tokpushback) {
  690.         tokpushback = 0;
  691.         return lasttoken;
  692.       }
  693.       lasttoken = 0;
  694.       while ((c = getc(infp)) == ' ' || c == '\t');
  695.       if (c == '\n') {
  696.         linno++;
  697.         return lasttoken = TNL;
  698.       }
  699.       p = toktext;
  700.       do {
  701.         if (c == EOF) {
  702.           *p = '\0';
  703.           error("EOF in middle of line");
  704.           exit(2);
  705.         }
  706.         if (p >= toktext + sizeof toktext - 2) {
  707.           *p = '\0';
  708.           error("Input token too long");
  709.           p = toktext;
  710.         }
  711.         *p++ = c;
  712.       } while ((c = getc(infp)) != ' ' && c != '\t' && c != '\n');
  713.       ungetc(c, infp);
  714.       *p = '\0';
  715.       return lasttoken = TWORD;
  716. }
  717.  
  718.  
  719.  
  720. /*
  721.  * Parse a string.
  722.  */
  723.  
  724. int
  725. getstring() {
  726.       int c;
  727.       char *p;
  728.  
  729.       toktext[0] = '\0';
  730.       lasttoken = 0;
  731.       while ((c = getc(infp)) == ' ' || c == '\t');
  732.       if (c == EOF) {
  733.         error("EOF in middle of line");
  734.         exit(2);
  735.       }
  736.       if (c != '"') {
  737.         ungetc(c, infp);
  738.         gettoken();
  739.         error("Expecting a quoted string");
  740.         return -1;
  741.       }
  742.       p = toktext;
  743.       for (;;) {
  744.         c = getc(infp);
  745.         if (c == '"')
  746.           break;
  747.         if (c == '\\') {
  748.           *p++ = c;
  749.           c = getc(infp);
  750.         }
  751.         if (c == EOF) {
  752.           *p = '\0';
  753.           error("EOF in middle of line");
  754.           exit(2);
  755.         }
  756.         if (c == '\n') {
  757.           ungetc(c, infp);
  758.           error("Unterminated string");
  759.           return -1;
  760.         }
  761.         if (p >= toktext + sizeof toktext - 2) {
  762.           *p = '\0';
  763.           error("String too long");
  764.           p = toktext;
  765.         }
  766.         *p++ = c;
  767.       }
  768.       *p = '\0';
  769.       lasttoken = TSTRING;
  770. }
  771.  
  772.  
  773. /*
  774.  * Parse the text in the last token string.
  775.  */
  776.  
  777.  
  778. void
  779. cvttext(doctl) {
  780.       register char *p, *q;
  781.       char *endp = toktext + strlen(toktext);
  782.       int n;
  783.       int c;
  784.  
  785.       q = tokstring;
  786.       for (p = toktext ; p < endp ; p++) {
  787.         if (q >= tokstring + 127) {
  788.           error("String exceeds 127 characters");    
  789.           break;
  790.         }
  791.         if (*p == '\\') {
  792.           switch (*++p) {
  793.           case 'b':  *q++ = '\b';  break;
  794.           case 'e':  *q++ = '\033'; break;    /* escape */
  795.           case 'f':  *q++ = '\f';  break;
  796.           case 'n':  *q++ = '\n';  break;
  797.           case 'r':  *q++ = '\r';  break;
  798.           case 's':  *q++ = ' ';   break;
  799.           case 't':  *q++ = '\t';  break;
  800.           case '0': case '1': case '2': case '3':
  801.           case '4': case '5': case '6': case '7':
  802.             c = *p - '0';
  803.             n = 3;
  804.             while (*++p >= '0' && *p <= '7' && --n > 0) {
  805.                   c = (c << 3) + *p - '0';
  806.             }
  807.             *q++ = c;
  808.             break;
  809.           default:
  810.             *q++ = *p;
  811.             break;
  812.           }
  813.         } else if (*p == '^' && doctl) {
  814.           if (*++p == '?')
  815.             *q++ = '\177';
  816.           else
  817.             *q++ = *p & 037;
  818.         } else {
  819.           *q++ = *p;
  820.         }
  821.       }
  822.       stringlen = q - tokstring;
  823. }
  824.  
  825.  
  826. int
  827. ateof() {
  828.       int c;
  829.  
  830.       if (feof(infp) || (c = getc(infp)) == EOF)
  831.         return 1;
  832.       ungetc(c, infp);
  833.       return 0;
  834. }
  835.  
  836.  
  837. char *
  838. saveblock(block, len)
  839.       char *block;
  840.       int len;
  841.       {
  842.       char *p;
  843.  
  844.       if ((p = malloc(len)) == NULL) {
  845.         error("Out of space");
  846.         exit(2);
  847.       }
  848.       bcopy(block, p, len);
  849.       return p;
  850. }
  851.  
  852.  
  853. void
  854. error(msg)
  855.       char *msg;
  856.       {
  857.       int lno;
  858.       static int lasterror = -1;
  859.  
  860.       lno = (lasttoken == TNL)? linno - 1 : linno;
  861.       if (lno != lasterror) {
  862.         lasterror = lno;
  863.         printf("%s:%d: %s", inputfile, lno, msg);
  864.         if (lasttoken == TNL)
  865.           printf(" (input token = NEWLINE)\n");
  866.         else
  867.           printf(" (input token = \"%s\")\n", toktext);
  868.       }
  869.       nerrors++;
  870. }
  871.  
  872.  
  873. int
  874. writeout() {
  875.       int i;
  876.       int tabno;
  877.       int stringno;
  878.       int stringloc;
  879.       struct abbrev *ap;
  880.  
  881.       if (debug)
  882.         return dbwriteout();
  883.       strcpy(outputfile, inputfile);
  884.       if ((i = strlen(inputfile)) < 5 || ! equal(inputfile + i - 5, ".bind"))
  885.         strcat(outputfile, ".bindc");
  886.       else
  887.         strcat(outputfile, "c");
  888.       if ((outfp = fopen(outputfile, "w")) == NULL) {
  889.         fprintf(stderr, "Can't create %s\n", outputfile);
  890.         return -1;
  891.       }
  892.       putsh(BINDMAGIC, outfp);
  893.       putc(VERSION, outfp);
  894.       putc(nmodes + nkeytab, outfp);
  895.       putsh(strnext - stringspace, outfp);
  896.       putsh(abbrevsize, outfp);
  897.       for (tabno = 0 ; tabno < nmodes ; tabno++) {
  898.         putkeytab(mode[tabno].keytab);
  899.       }
  900.       for (tabno = 0 ; tabno < nkeytab ; tabno++) {
  901.         putkeytab(keytab[tabno]);
  902.       }
  903.       for (i = 0 ; i < NSYNTAX ; i++)
  904.         fwrite(syntax[i].bitmap, sizeof syntax[i].bitmap, 1, outfp);
  905.       fwrite(stringspace, strnext - stringspace, 1, outfp);
  906.       for (i = 0, ap = abbrev ; i < nabbrev ; i++, ap++) {
  907.         putc(ap->fromlen, outfp);    abbrevsize -= 1;
  908.         fwrite(ap->from, ap->fromlen, 1, outfp); abbrevsize -= ap->fromlen;
  909.         putc(ap->tolen, outfp);    abbrevsize -= 1;
  910.         fwrite(ap->to, ap->tolen, 1, outfp);  abbrevsize -= ap->tolen;
  911.       }
  912.       if (abbrevsize != 0)
  913.         abort();
  914.       if (ferror(outfp) || fclose(outfp) == EOF) {
  915.         fprintf(stderr, "Write error on %s\n", outputfile);
  916.         return -1;
  917.       }
  918.       return 0;
  919. }
  920.  
  921.  
  922. void
  923. putkeytab(tab)
  924.       struct cmd *tab;
  925.       {
  926.       struct cmd *cp;
  927.       int ch;
  928.  
  929.       cp = tab;
  930.       for (ch = 0 ; ch <= 127 ; ch++) {
  931.         putc(cp->type, outfp);
  932.         cp++;
  933.       }
  934.       cp = tab;
  935.       for (ch = 0 ; ch <= 127 ; ch++) {
  936.         if (cp->type == C_PFXTBL)
  937.           putc(cp->index + nmodes, outfp);
  938.         else
  939.           putc(cp->index, outfp);
  940.         cp++;
  941.       }
  942. }
  943.  
  944.  
  945. void
  946. putsh(i, fp)
  947.       FILE *fp;
  948.       {
  949.       putc(i, fp);
  950.       putc(i >> 8, fp);
  951. }
  952.  
  953.  
  954. #if 1
  955. int
  956. dbwriteout() {
  957.       int i;
  958.       int tabno;
  959.       int stringno;
  960.       int stringloc;
  961.       struct abbrev *ap;
  962.       char *p;
  963.  
  964.       strcpy(outputfile, inputfile);
  965.       if ((i = strlen(inputfile)) < 5 || ! equal(inputfile + i - 5, ".bind"))
  966.         strcat(outputfile, ".bindc");
  967.       else
  968.         strcat(outputfile, "c");
  969.       if ((outfp = fopen(outputfile, "w")) == NULL) {
  970.         fprintf(stderr, "Can't create %s\n", outputfile);
  971.         return -1;
  972.       }
  973.       for (tabno = 0 ; tabno < nmodes ; tabno++) {
  974.         fprintf(outfp, "keytab for mode %d:\n", tabno);
  975.         dbputkeytab(mode[tabno].keytab);
  976.       }
  977.       for (tabno = 0 ; tabno < nkeytab ; tabno++) {
  978.         fprintf(outfp, "keytab %d:\n", tabno + nmodes);
  979.         dbputkeytab(keytab[tabno]);
  980.       }
  981.       for (i = 0 ; i < NSYNTAX ; i++)
  982.         dbputsyntax(syntax[i].name, syntax[i].bitmap);
  983.       fprintf(outfp, "\nstrings:\n");
  984.       stringloc = 0;
  985.       for (stringno = 0 ; stringno < nstrings ; stringno++) {
  986.         fprintf(outfp, "%-4d ", i = stringspace[stringloc++]);
  987.         while (--i >= 0)
  988.           outchar(stringspace[stringloc++]);
  989.         putc('\n', outfp);
  990.       }
  991.       fprintf(outfp, "\nAbbreviations:\n");
  992.       for (stringno = 0, ap = abbrev ; stringno < nabbrev ; stringno++, ap++) {
  993.         i = ap->fromlen, p = ap->from;
  994.         while (--i >= 0)
  995.           outchar(*p++);
  996.         fputs(": ", outfp);
  997.         i = ap->tolen, p = ap->to;
  998.         while (--i >= 0)
  999.           outchar(*p++);
  1000.         putc('\n', outfp);
  1001.         abbrevsize -= ap->fromlen + ap->tolen + 2;
  1002.       }
  1003.       if (abbrevsize != 0)
  1004.         abort();
  1005. }
  1006.  
  1007.  
  1008.  
  1009. dbputkeytab(tab)
  1010.       struct cmd *tab;
  1011.       {
  1012.       struct cmd *cp;
  1013.       int ch;
  1014.  
  1015.       cp = tab;
  1016.       for (ch = 0 ; ch <= 127 ; ch++) {
  1017.         outchar1(ch);
  1018.         putc(' ', outfp);
  1019.         if (cp->type == C_FUNC) {
  1020.           fprintf(outfp, "%s\n", command[cp->index]);
  1021.         } else if (cp->type == C_PFXTBL) {
  1022.           fprintf(outfp, "keytab %d\n", cp->index + nmodes);
  1023.         } else if (cp->type == C_INSERT) {
  1024.           fprintf(outfp, "insert %d\n", cp->index);
  1025.         } else if (cp->type == C_UNDEF) {
  1026.           fprintf(outfp, "<undef>\n");
  1027.         } else if (cp->type == C_UNSET) {
  1028.           fprintf(outfp, "{}\n");
  1029.         } else {
  1030.           fprintf(outfp, "type = %d, index = %d\n", cp->type, cp->index);
  1031.         }
  1032.         cp++;
  1033.       }
  1034.       putc('\n', outfp);
  1035.  
  1036. }
  1037.  
  1038.  
  1039.  
  1040. dbputsyntax(name, syntax)
  1041.       char *name;
  1042.       char *syntax;
  1043.       {
  1044.       int c;
  1045.       int start;
  1046.  
  1047.       fprintf(outfp, "%s syntax: ", name);
  1048.       start = -1;
  1049.       for (c = 0 ; c <= 128 ; c++) {
  1050.         if (c != 128 && syntax[c >> 3] & 1 << (c & 07)) {
  1051.           if (start < 0) {
  1052.             start = c;
  1053.           }
  1054.         } else {
  1055.           if (start >= 0) {
  1056.             outchar(start);
  1057.             if (start != c - 1) {
  1058.                   putc('-', outfp);
  1059.                   outchar(c - 1);
  1060.             }
  1061.             start = -1;
  1062.           }
  1063.         }
  1064.       }
  1065.       putc('\n', outfp);
  1066. }
  1067.  
  1068.  
  1069.  
  1070. outchar1(ch) {
  1071.       if (ch < ' ')
  1072.         fprintf(outfp, "^%c", ch ^ 0100);
  1073.       else if (ch == ' ')
  1074.         fprintf(outfp, "SP");
  1075.       else if (ch == '\177')
  1076.         fprintf(outfp, "^?");
  1077.       else
  1078.         fprintf(outfp, "%c ", ch);
  1079. }
  1080.  
  1081.  
  1082.  
  1083. outchar(ch) {
  1084.       if (ch < ' ')
  1085.         fprintf(outfp, "^%c", ch ^ 0100);
  1086.       else if (ch == '\177')
  1087.         fprintf(outfp, "^?");
  1088.       else
  1089.         putc(ch, outfp);
  1090. }
  1091. #endif
  1092. EOF
  1093. if test `wc -c < kbind.c` -ne 23061
  1094. then    echo 'kbind.c is the wrong size'
  1095. fi
  1096. echo extracting makefile
  1097. cat > makefile <<\EOF
  1098. # Copyright (C) 1989 by Kenneth Almquist.
  1099.  
  1100. FILES=atty.o output.o ed.o edfuncs.o update.o dftbind.o regex.o
  1101.  
  1102. #CC=gcc
  1103. DEBUG=-g
  1104. CFLAGS=$(DEBUG)
  1105. LIBS=-ltermcap
  1106. #P=&    # for Sequent's parallel make
  1107.  
  1108. all:$P kbind atty fmatch atty.1 atty.bindc
  1109.  
  1110. clean:
  1111.     rm -f *.o
  1112.  
  1113. clobber:
  1114.     rm -f *.o atty kbind fmatch edfuncs.c dftbind.c atty.1 atty.bindc
  1115.  
  1116. atty:$P $(FILES)
  1117.     $(CC) -o temp $(FILES) $(LIBS)
  1118.     mv -f temp $@
  1119.  
  1120. kbind: kbind.o
  1121.     $(CC) -o $@ kbind.o
  1122.  
  1123. edfuncs.c: kbind
  1124.     ./kbind -makefuncs
  1125.  
  1126. dftbind.c:
  1127.     echo "char dftbind[] = \"`pwd`/atty.bindc\";" > $@
  1128.  
  1129. atty.bindc: atty.bind kbind
  1130.     ./kbind atty.bind
  1131.  
  1132. fmatch: fmatch.o
  1133.     $(CC) -g -o $@ fmatch.o
  1134.  
  1135. atty.1: atty.1.mk
  1136.     sh atty.1.mk > atty.1
  1137.  
  1138. atty.o: atty.h attyed.h
  1139. ed.o: attyed.h ed.h bind.h regex.h
  1140. kbind.o: bind.h
  1141. output.o: atty.h attyed.h
  1142. update.o: attyed.h ed.h
  1143. EOF
  1144. if test `wc -c < makefile` -ne 794
  1145. then    echo 'makefile is the wrong size'
  1146. fi
  1147. echo extracting output.c
  1148. cat > output.c <<\EOF
  1149. /*
  1150.  * Copyright (C) 1989 by Kenneth Almquist.
  1151.  */
  1152.  
  1153. #include <stdio.h>
  1154. #include <sgtty.h>    /* for atty.h */
  1155. #include "atty.h"
  1156. #include "attyed.h"
  1157.  
  1158.  
  1159.  
  1160. int outstate;
  1161. int column;
  1162. char outline[COLUMNS];
  1163. char prompt[COLUMNS];
  1164. int promptlen;
  1165. int param[2];
  1166. char strparam[256];
  1167. int nparam;
  1168. char *strparamp;
  1169. char esccmd;
  1170. int *curnumber;
  1171. int promptcode;
  1172. int promptset;
  1173. char lastoutline[COLUMNS];
  1174. int lastoutlinelen;
  1175.  
  1176.  
  1177. /*
  1178.  * All output passes through the outchars routine.  The routine keeps
  1179.  * track of the current column and identifies escape sequences that
  1180.  * are interpreted by atty itself.
  1181.  */
  1182.  
  1183. outchars(p, n)
  1184.       char *p;
  1185.       int n;
  1186.       {
  1187.       char c;
  1188.       int newcol;
  1189.       int i;
  1190.       char *savep;
  1191.       char *q;
  1192.       int savecol = column;
  1193.  
  1194.       savep = p;
  1195.       switch (outstate) {
  1196.       case 0:
  1197.       state0:    /* base state */
  1198.         while (--n >= 0) {
  1199.           c = *p++;
  1200.           if (c >= ' ' && c <= '~') {
  1201.             if (column < COLUMNS)
  1202.                   outline[column] = c;
  1203.             column++;
  1204.           } else if (c == '\t') {
  1205.             newcol = (column + 8) &~ 07;
  1206.             while (column < newcol && column < COLUMNS)
  1207.                   outline[column++] = ' ';
  1208.             column = newcol;
  1209.           } else if (c == '\r') {
  1210.             if ((lastoutlinelen = column) > COLUMNS)
  1211.                 lastoutlinelen = COLUMNS;
  1212.             bcopy(outline, lastoutline, lastoutlinelen);
  1213.             column = 0;
  1214.           } else if (c == '\033') {    /* ESCAPE */
  1215.             outstate = 1;
  1216.             goto state1;
  1217.           } else if (c == '\b') {
  1218.             if (column > 0)
  1219.                   column--;
  1220.           }
  1221.         }
  1222.         break;
  1223.       case 1:
  1224.       state1:    /* escape character seen */
  1225.         if (--n < 0)
  1226.           break;
  1227.         c = *p++;
  1228.         if (c == '[') {
  1229.           outstate = 2;
  1230.           nparam = 0;
  1231.           param[0] = param[1] = 0;
  1232.           curnumber = NULL;
  1233.           goto state2;
  1234.         } else if (c == ']') {
  1235.           if (p - 2 > savep) {
  1236.             dispoff(savecol);
  1237.             outreal(savep, p - 2 - savep);
  1238.           }
  1239.           outstate = 3;
  1240.           goto state3;
  1241.         } else if (c == 'H') {    /* ESC H = home on some terminals */
  1242.           column = 0;
  1243.           outstate = 0;
  1244.           goto state0;
  1245.         } else {
  1246.           outstate = 0;
  1247.           goto state0;
  1248.         }
  1249.       case 2:
  1250.       state2:    /* ESC [ seen */
  1251.         while (--n >= 0) {
  1252.           c = *p++;
  1253.           if (c >= '0' && c <= '9') {
  1254.             if (curnumber != NULL) {
  1255.                   *curnumber = *curnumber * 10 + c - '0';
  1256.             } else if (nparam < 2) {
  1257.                   curnumber = ¶m[nparam++];
  1258.                   *curnumber = c - '0';
  1259.             }
  1260.           } else if (c == '?') {
  1261.             /* ignore it for now */
  1262.           } else if (c == ';') {
  1263.             curnumber = NULL;
  1264.           } else {
  1265.             goto gotescape;
  1266.           }
  1267.         }
  1268.         break;
  1269.  
  1270. gotescape:
  1271.         /* got a complete escape sequence */
  1272.         switch (c) {
  1273.           case 'H':
  1274.             column = param[1] > 0? param[1] - 1 : 0;
  1275.             break;
  1276.           case 'C':
  1277.             column += param[0];
  1278.             break;
  1279.           case 'D':
  1280.             if ((column -= param[0]) < 0)
  1281.                   column = 0;
  1282.             break;
  1283.           case 'L':  case'M':
  1284.             column = 0;
  1285.             break;
  1286.           case 'J':
  1287.             if (param[0] == 1 || param[0] == 2) {
  1288.                   for (i = 0 ; i < column && i < COLUMNS; i++)
  1289.                     outline[i] = ' ';
  1290.             }
  1291.             break;
  1292.         }
  1293.         outstate = 0;
  1294.         goto state0;
  1295.       case 3:
  1296.       state3:    /* got ESC ], which introduces an atty control sequence */
  1297.         if (--n < 0)
  1298.           break;
  1299.         c = *p++;
  1300.         if (c == 'P' || c == 'I' || c == 'D') {
  1301.           esccmd = c;
  1302.           strparamp = strparam;
  1303.           outstate = 4;
  1304.           goto state4;
  1305.         } else {
  1306.           dispoff(savecol);
  1307.           ttyoutc('\033');
  1308.           ttyoutc(']');
  1309.           ttyoutc(c);
  1310.           savep = p - 1;
  1311.           outstate = 0;
  1312.           goto state0;
  1313.         }
  1314.         break;
  1315.       case 4:
  1316.       state4:    /* reading prompt following ESC ] P */
  1317.         while (--n >= 0) {
  1318.           c = *p++;
  1319.           if (c == '\n') {
  1320.             *strparamp = '\0';
  1321.             goto myesc;
  1322.           }
  1323.           if (c != '\r' && strparamp < &strparam[255]) {
  1324.             *strparamp++ = c;
  1325.           }
  1326.         }
  1327.         break;
  1328.  
  1329. myesc:
  1330.         /* got an ESC ] ... sequence */
  1331.         switch (esccmd) {
  1332.         case 'P':
  1333.           if (promptset) {
  1334.             freezedisp(0);
  1335. #ifdef notdef
  1336.             if (column != 0) {
  1337.                   ttyoutc('\r');
  1338.                   ttyoutc('\n');
  1339.             }
  1340.             for (column = 0 ; prompt[column] ; column++)
  1341.                   ttyoutc(prompt[column]);
  1342.             bcopy(prompt, outline, column);
  1343. #endif
  1344.           }
  1345.           dispoff(savecol);
  1346.           q = strparam;
  1347.           i = 0;
  1348.           while (*q >= '0' && *q <= '9') {
  1349.             i = 10 * i + *q - '0';
  1350.             q++;
  1351.           }
  1352.           if (*q == ';')
  1353.             q++;
  1354.           promptcode = i;
  1355.           if (strlen(q) > COLUMNS - 1)
  1356.                   q[COLUMNS - 1] = '\0';
  1357.           strcpy(prompt, q);
  1358.           promptset = 1;
  1359.           break;
  1360.         case 'D':
  1361.           promptset = 0;
  1362.           break;
  1363.         case 'I':
  1364.           insertchars(strparam, strlen(strparam));
  1365.           break;
  1366.         }
  1367.         savep = p;
  1368.         outstate = 0;
  1369.         goto state0;
  1370.       }
  1371.       if (outstate < 3 && savep != p) {
  1372.         dispoff(savecol);
  1373.         outreal(savep, p - savep);
  1374.       }
  1375. }
  1376. EOF
  1377. if test `wc -c < output.c` -ne 4576
  1378. then    echo 'output.c is the wrong size'
  1379. fi
  1380. echo extracting update.c
  1381. cat > update.c <<\EOF
  1382. /*
  1383.  * Update the display of the line being edited on the screen.
  1384.  * Copyright (C) 1989 by Kenneth Almquist.
  1385.  */
  1386.  
  1387.  
  1388. #include "attyed.h"
  1389. #include "ed.h"
  1390. #include <ctype.h>
  1391.  
  1392. #ifndef NULL
  1393. #define NULL 0
  1394. #endif
  1395.  
  1396.  
  1397. struct displine {
  1398.       char *text;        /* text of line */
  1399.       int len;            /* length of line */
  1400. };
  1401.  
  1402.  
  1403. int scrnwidth;            /* width of screen */
  1404. int eddisplay;            /* if nonzero, editor display is valid */
  1405. int needbeep;            /* if nonzero, beep on next refresh */
  1406. struct displine virtscrn[60];    /* what the screen should look like */
  1407. struct displine realscrn[60];    /* what the screen does look like */
  1408. int vslines;            /* number of lines on virtual screen */
  1409. int rslines;            /* number of lines on real screen */
  1410. int virtline;            /* cursor position in virtscrn */
  1411. int virtcol;            /* cursor position in virtscrn */
  1412. char *virtptr;            /* &virtscrn[virtline].text[virtcol] */
  1413. int *virtlen;            /* &virtscrn[virtline].len */
  1414. int realline;            /* position of cursor on real screen */
  1415. int realcol;            /* position of cursor on real screen */
  1416. int lastrealline;        /* last real line on the screen */
  1417. int startline;            /* end of prompt */
  1418. int startcol;            /* end of prompt */
  1419. char tcspace[120];        /* strings from termcap are stored here */
  1420. int tc_am;            /* cursor wraps around at right of screen */
  1421. char *tc_bc;            /* backspace */
  1422. char *tc_bl;            /* bell */
  1423. int tc_bs;            /* if set, terminal can backspace */
  1424. char *tc_ce;            /* clear to end of line */
  1425. int tc_co;            /* default width of screen */
  1426. char *tc_do;            /* cursor down one line */
  1427. char *tc_nc;            /* cursor right on column */
  1428. char *tc_up;            /* cursor up one line */
  1429. int tc_xn;            /* a newline is ignored after wrap around */
  1430. char PC;            /* pad character (for termcap routines) */
  1431. extern int errno;
  1432.  
  1433.  
  1434. #ifdef __STDC__
  1435. void virtgoto(int, int);
  1436. void drawch(int);
  1437. void realgoto(int, int);
  1438. void copytoreal(int, int);
  1439. void allocline(struct displine *);
  1440. #else
  1441. void virtgoto();
  1442. void drawch();
  1443. void realgoto();
  1444. void copytoreal();
  1445. void allocline();
  1446. #endif
  1447.  
  1448. #ifdef __STDC__
  1449. void ttyoutc(int);
  1450. char *getenv(char *);
  1451. int tgetent(char *, char *);
  1452. int tgetnum(char *);
  1453. int tgetflag(char *);
  1454. char *tgetstr(char *, char **);
  1455. void tputs(char *, int, void (*)(int));
  1456. char *malloc(unsigned);
  1457. #else
  1458. void ttyoutc();
  1459. char *getenv();
  1460. int tgetent();
  1461. int tgetnum();
  1462. int tgetflag();
  1463. char *tgetstr();
  1464. void tputs();
  1465. char *malloc();
  1466. #endif
  1467.  
  1468.  
  1469.  
  1470. /*
  1471.  * Read the termcap entry for this terminal.
  1472.  */
  1473.  
  1474. void
  1475. gettermcap() {
  1476.       char *termtype;
  1477.       char buffer[1024];
  1478.       char *tcp = tcspace;
  1479.       char *tc_pc;
  1480.  
  1481.       errno = 0;
  1482.       if ((termtype = getenv("TERM")) == NULL)
  1483.         badinit("$TERM not set");
  1484.       if (tgetent(buffer, termtype) <= 0)
  1485.         badinit("Termcap entry not found");
  1486.       tc_am = tgetflag("am");
  1487.       tc_bs = tgetflag("bs");
  1488.       tc_bc = tgetstr("bc", &tcp);
  1489.       tc_bl = tgetstr("bl", &tcp);
  1490.       tc_ce = tgetstr("ce", &tcp);
  1491.       tc_co = tgetnum("co");
  1492.       tc_do = tgetstr("do", &tcp);
  1493.       tc_nc = tgetstr("nc", &tcp);
  1494.       tc_pc = tgetstr("pc", &tcp);
  1495.       tc_up = tgetstr("up", &tcp);
  1496.       tc_xn = tgetflag("xn");
  1497.       PC = (tc_pc != NULL)? *tc_pc : '\0';
  1498.       if (tc_up == NULL)
  1499.         badinit("Atty can only run a terminal with a cursor-up escape sequence");
  1500.       scrnwidth = tc_co;
  1501. }
  1502.  
  1503.  
  1504.  
  1505. void
  1506. newscrnwidth(width) {
  1507.       struct displine *lp;
  1508.       int disp = eddisplay;
  1509.  
  1510.       if (width <= 1)
  1511.         width = tc_co;
  1512.       if (width == scrnwidth)
  1513.         return;
  1514.       if (disp)
  1515.         dispoff(column);
  1516.       for (lp = virtscrn ; lp->text ; lp++) {
  1517.         free(lp->text);
  1518.         lp->text = NULL;
  1519.       }
  1520.       vslines = 0;
  1521.       for (lp = realscrn ; lp->text ; lp++) {
  1522.         free(lp->text);
  1523.         lp->text = NULL;
  1524.       }
  1525.       scrnwidth = width;
  1526.       if (disp)
  1527.         refresh();
  1528. }
  1529.  
  1530.  
  1531.  
  1532. void
  1533. refresh() {
  1534.       struct displine *lp;
  1535.       char *p;
  1536.       int pointline, pointcol;
  1537.  
  1538.       if (eddisplay == 0) {
  1539.         if (realscrn[0].text == NULL)
  1540.           allocline(&realscrn[0]);
  1541.         if (virtscrn[0].text == NULL)
  1542.           allocline(&virtscrn[0]);
  1543.         for (lp = realscrn ; lp->text != NULL ; lp++)
  1544.           lp->len = 0;
  1545.         startcol = column % scrnwidth;
  1546.         startline = 0;
  1547.         realcol = startcol;
  1548.         realline = 0;
  1549.         if (column != 0) {
  1550.           bcopy(outline, realscrn[0].text, realcol);
  1551.           realscrn[0].len = realcol;
  1552.           bcopy(outline, virtscrn[0].text, realcol);
  1553.           virtscrn[0].len = realcol;
  1554.           if (promptset) {
  1555.             startcol = 0;
  1556.             startline = 1;
  1557.           }
  1558.         }
  1559.         if (promptset) {
  1560.           virtgoto(startline, startcol);
  1561.           for (p = prompt ; *p ; p++)
  1562.             drawch(*p);
  1563.           startline = virtline;
  1564.           startcol = virtcol;
  1565.         }
  1566.         lastrealline = 0;
  1567.         eddisplay = 1;
  1568.       }
  1569.       /* erase everything following the prompt from the virtual screen */
  1570.       virtgoto(startline, startcol);
  1571.       lp = &virtscrn[startline];
  1572.       lp->len = startcol;
  1573.       while ((++lp)->text != NULL)
  1574.         lp->len = 0;
  1575.       if (editprompt)
  1576.         drawch(editprompt);
  1577.       pointcol = -1;
  1578.       if (ttymode.echo) {
  1579.         for (p = curline ; p < endcurline ; p++) {
  1580.           if (p == point) {
  1581.             pointline = virtline;
  1582.             pointcol = virtcol;
  1583.           }
  1584.           drawch(*p);
  1585.         }
  1586.       }
  1587.       if (pointcol < 0) {
  1588.         pointline = virtline;
  1589.         pointcol = virtcol;
  1590.       }
  1591.       copytoreal(pointline, pointcol);
  1592. }
  1593.  
  1594.  
  1595. /*
  1596.  * Copy the virtual screen to the real screen.
  1597.  */
  1598.  
  1599. void
  1600. copytoreal(pointline, pointcol) {
  1601.       char *p;
  1602.       char *r;
  1603.       int line;
  1604.       int len;
  1605.       int limit;
  1606.       int col;
  1607.  
  1608.       for (line = 0 ; line <= virtline ; line++) {
  1609.         len = virtscrn[line].len;
  1610.         p = virtscrn[line].text;
  1611.         limit = realscrn[line].len;
  1612.         r = realscrn[line].text;
  1613.         if (r == NULL) {
  1614.           allocline(&realscrn[line]);
  1615.           r = realscrn[line].text;
  1616.         }
  1617.         if (limit > len)
  1618.           limit = len;
  1619.         for (col = 0 ; col < limit ; col++) {
  1620.           if (*p != *r) {
  1621.             if (realline != line || realcol != col)
  1622.                   realgoto(line, col);
  1623.             ttyoutc(*p);
  1624.             realcol++;
  1625.             *r = *p;
  1626.           }
  1627.           p++;
  1628.           r++;
  1629.         }
  1630.         for ( ; col < len ; col++) {
  1631.           if (*p != ' ') {
  1632.             if (realline != line || realcol != col)
  1633.                   realgoto(line, col);
  1634.             ttyoutc(*p);
  1635.             realcol++;
  1636.           }
  1637.           *r++ = *p++;
  1638.         }
  1639.         limit = realscrn[line].len;
  1640.         if (col < limit) {
  1641.           if (tc_ce == NULL || limit - col == 1) {
  1642.             for ( ; col < limit ; col++) {
  1643.                   if (*r++ != ' ') {
  1644.                     if (realline != line || realcol != col)
  1645.                       realgoto(line, col);
  1646.                     ttyoutc(' ');
  1647.                     realcol++;
  1648.                   }
  1649.             }
  1650.           } else {
  1651.             realgoto(line, col);
  1652.             tputs(tc_ce, 1, ttyoutc);
  1653.           }
  1654.         }
  1655.         if (realcol >= scrnwidth) {
  1656.           if (tc_xn || ! tc_am)
  1657.             outreal("\r\n", 2);
  1658.           realcol = 0;
  1659.           realline++;
  1660.         }
  1661.         realscrn[line].len = virtscrn[line].len;
  1662.       }
  1663.       while (line <= lastrealline) {
  1664.         if (realscrn[line].len > 0) {
  1665.           if (tc_ce) {
  1666.             realgoto(line, 0);
  1667.             tputs(tc_ce, 1, ttyoutc);
  1668.           } else {
  1669.             r = realscrn[line].text;
  1670.             limit = realscrn[line].len;
  1671.             for (col = 0 ; col < limit ; col++) {
  1672.                   if (*r++ != ' ') {
  1673.                     if (realline != line || realcol != col)
  1674.                       realgoto(line, col);
  1675.                     ttyoutc(' ');
  1676.                     realcol++;
  1677.                   }
  1678.             }
  1679.             if (realcol >= scrnwidth) {
  1680.                   if (tc_xn || ! tc_am)
  1681.                     outreal("\r\n", 2);
  1682.                   realcol = 0;
  1683.                   realline++;
  1684.             }
  1685.           }
  1686.           realscrn[line].len = 0;
  1687.         }
  1688.         line++;
  1689.       }
  1690.       realgoto(pointline, pointcol);
  1691.       if (needbeep) {
  1692.         if (tc_bl)
  1693.           tputs(tc_bl, 1, ttyoutc);
  1694.         needbeep = 0;
  1695.       }
  1696.       lastrealline = virtline;
  1697. }
  1698.  
  1699.  
  1700.  
  1701. /*
  1702.  * Move to beyond the end of the edited stuff, and turn the display off.
  1703.  */
  1704.  
  1705. void
  1706. movetoend() {
  1707.       realgoto(lastrealline, 0);
  1708.       ttyoutc('\n');
  1709.       eddisplay = 0;
  1710.       column = 0;
  1711.       promptset = 0;
  1712. }
  1713.  
  1714.  
  1715. /*
  1716.  * Output the line being edited to the display, and freeze it there.
  1717.  * If the data flag is zero, only freeze the prompt.
  1718.  */
  1719.  
  1720. void
  1721. freezedisp(data) {
  1722.       int i;
  1723.       struct displine *lp;
  1724.       int save_echo;
  1725.  
  1726.       save_echo = ttymode.echo;
  1727.       ttymode.echo = data;
  1728.       refresh();
  1729.       ttymode.echo = save_echo;
  1730.       eddisplay = 0;
  1731.       column = realcol;
  1732.       lp = &realscrn[realline];
  1733.       for (i = 0 ; i < column ; i++) {
  1734.         outline[i] = (i < lp->len)? lp->text[i] : ' ';
  1735.       }
  1736.       promptset = 0;
  1737. }
  1738.  
  1739.  
  1740.  
  1741. /*
  1742.  * Turn display off.
  1743.  */
  1744.  
  1745. void
  1746. dispoff(col) {
  1747.       int line;
  1748.  
  1749.       if (eddisplay == 0)
  1750.         return;
  1751.       col = col % scrnwidth;
  1752.       virtscrn[0].len = col;
  1753.       for (line = 1 ; line <= lastrealline ; line++)
  1754.         virtscrn[line].len = 0;
  1755.       copytoreal(0, col);
  1756.       eddisplay = 0;
  1757. }
  1758.  
  1759.  
  1760.  
  1761. void
  1762. virtgoto(line, col) {
  1763.       struct displine *lp;
  1764.       char *p;
  1765.  
  1766.       while (vslines <= line) {
  1767.         allocline(&virtscrn[vslines]);
  1768.         vslines++;
  1769.       }
  1770.       lp = &virtscrn[line];
  1771.       if (lp->len < col) {
  1772.         p = &lp->text[lp->len];
  1773.         do *p++ = ' ';
  1774.         while (++lp->len < col);
  1775.       }
  1776.       virtline = line;
  1777.       virtcol = col;
  1778.       virtptr = &lp->text[col];
  1779.       virtlen = &lp->len;
  1780. }
  1781.  
  1782.  
  1783. void
  1784. drawch(c)
  1785.       char c;
  1786.       {
  1787.       if (! isprint(c)) {
  1788.         if (c == '\t') {
  1789.           do drawch(' ');
  1790.           while ((virtcol & 07) != 0);
  1791.           return;
  1792.         } else {
  1793.           drawch('^');
  1794.           c ^= 0100;
  1795.         }
  1796.       }
  1797.       *virtptr++ = c;
  1798.       virtcol++;
  1799.       if (*virtlen < virtcol)
  1800.         *virtlen = virtcol;
  1801.       if (virtcol >= scrnwidth) {
  1802.         virtgoto(virtline + 1, 0);
  1803.       }
  1804. }
  1805.  
  1806.  
  1807. /*
  1808.  * Goto the specified location on the real screen.  Note that we may
  1809.  * scroll the screen, so we must use line feed rather than do for
  1810.  * downward motion.
  1811.  */
  1812.  
  1813. void
  1814. realgoto(line, col) {
  1815.       char *text;
  1816.       int len;
  1817.  
  1818.       while (realline > 0 && realline > line) {
  1819.         tputs(tc_up, 1, ttyoutc);
  1820.         realline--;
  1821.       }
  1822.       while (realline < line) {
  1823. #ifdef notdef
  1824.         tputs(tc_do, 1, ttyoutc);
  1825. #else
  1826.         ttyoutc('\n');
  1827. #endif
  1828.         realline++;
  1829.       }
  1830.       if (col < realcol - col) {
  1831.         ttyoutc('\r');
  1832.         realcol = 0;
  1833.       }
  1834.       if (realcol > col) {
  1835.         if (tc_bc) {
  1836.           do {
  1837.             tputs(tc_bc, 1, ttyoutc);
  1838.           } while (--realcol > col);
  1839.         } else {
  1840.           do {
  1841.             ttyoutc('\b');
  1842.           } while (--realcol > col);
  1843.         }
  1844.       }
  1845.       if (realcol < col) {
  1846.         text = realscrn[realline].text;
  1847.         len = realscrn[realline].len;
  1848.         do {
  1849.           ttyoutc(realcol < len? text[realcol] : ' ');
  1850.         } while (++realcol < col);
  1851.       }
  1852.       if (line == 0 && realline > 0) {
  1853.         tputs(tc_up, 1, ttyoutc);
  1854.         realline--;
  1855.       }
  1856. }
  1857.  
  1858.  
  1859.  
  1860. void
  1861. allocline(lp)
  1862.       struct displine *lp;
  1863.       {
  1864.       char *p;
  1865.  
  1866.       if (lp->text != NULL)
  1867.         return;
  1868.       if ((p = malloc(scrnwidth)) == NULL)
  1869.         fatal("Malloc line failed");
  1870.       lp->text = p;
  1871.       lp->len = 0;
  1872. }
  1873. EOF
  1874. if test `wc -c < update.c` -ne 10496
  1875. then    echo 'update.c is the wrong size'
  1876. fi
  1877. echo extracting vi.bind
  1878. cat > vi.bind <<\EOF
  1879. # A very half-hearted attempt at a vi mode.
  1880.  
  1881. mode 0
  1882. default        self-insert
  1883. b    ^H    delete-backward-char
  1884. b    ^J    newline-and-insert
  1885. b    \r    newline
  1886. b    ^V    quoted-insert
  1887. b    ^W    backward-kill-word
  1888. b    ^X    kill-input
  1889. b    ^Z    tty-susp
  1890. b    ^[    mode-1
  1891. b    \034    tty-quit
  1892. b    \037    end-of-file
  1893. b    \177    tty-intr
  1894.  
  1895. mode 1
  1896. default        undefined
  1897. b    ^H    backward-char
  1898. b    ^J    newline-and-insert
  1899. b    \r    newline
  1900. b    ^Z    tty-susp
  1901. b    \034    tty-quit
  1902. b    \037    end-of-file
  1903. b    \s    forward-char
  1904. b    +    next-history
  1905. b    -    previous-history
  1906. b    0    digit-argument
  1907. b    1    digit-argument
  1908. b    2    digit-argument
  1909. b    3    digit-argument
  1910. b    4    digit-argument
  1911. b    5    digit-argument
  1912. b    6    digit-argument
  1913. b    7    digit-argument
  1914. b    8    digit-argument
  1915. b    9    digit-argument
  1916. b    /    re-search-forward
  1917. b    ?    re-search-backward
  1918. b    B    backward-word
  1919. b    W    forward-word
  1920. b    a    mode-0
  1921. b    b    backward-word
  1922. b    e    forward-word
  1923. b    h    backward-char
  1924. b    i    mode-0
  1925. b    j    previous-history
  1926. b    k    next-history
  1927. b    l    forward-char
  1928. b    w    forward-word
  1929. b    x    delete-backward-char
  1930. b    \177    tty-intr
  1931.  
  1932. b    db    backward-kill-word
  1933. b    dd    kill-input
  1934. b    dw    kill-word
  1935. EOF
  1936. if test `wc -c < vi.bind` -ne 974
  1937. then    echo 'vi.bind is the wrong size'
  1938. fi
  1939. echo extracting regex.h
  1940. cat > regex.h <<\EOF
  1941. /* Definitions for data structures callers pass the regex library.
  1942.    Copyright (C) 1985 Free Software Foundation, Inc.
  1943.  
  1944.                NO WARRANTY
  1945.  
  1946.   BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
  1947. NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
  1948. WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
  1949. RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
  1950. WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
  1951. BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1952. FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY
  1953. AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE
  1954. DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
  1955. CORRECTION.
  1956.  
  1957.  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
  1958. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
  1959. WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
  1960. LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
  1961. OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
  1962. USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
  1963. DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
  1964. A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
  1965. PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
  1966. DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  1967.  
  1968.         GENERAL PUBLIC LICENSE TO COPY
  1969.  
  1970.   1. You may copy and distribute verbatim copies of this source file
  1971. as you receive it, in any medium, provided that you conspicuously and
  1972. appropriately publish on each copy a valid copyright notice "Copyright
  1973. (C) 1985 Free Software Foundation, Inc."; and include following the
  1974. copyright notice a verbatim copy of the above disclaimer of warranty
  1975. and of this License.  You may charge a distribution fee for the
  1976. physical act of transferring a copy.
  1977.  
  1978.   2. You may modify your copy or copies of this source file or
  1979. any portion of it, and copy and distribute such modifications under
  1980. the terms of Paragraph 1 above, provided that you also do the following:
  1981.  
  1982.     a) cause the modified files to carry prominent notices stating
  1983.     that you changed the files and the date of any change; and
  1984.  
  1985.     b) cause the whole of any work that you distribute or publish,
  1986.     that in whole or in part contains or is a derivative of this
  1987.     program or any part thereof, to be licensed at no charge to all
  1988.     third parties on terms identical to those contained in this
  1989.     License Agreement (except that you may choose to grant more extensive
  1990.     warranty protection to some or all third parties, at your option).
  1991.  
  1992.     c) You may charge a distribution fee for the physical act of
  1993.     transferring a copy, and you may at your option offer warranty
  1994.     protection in exchange for a fee.
  1995.  
  1996. Mere aggregation of another unrelated program with this program (or its
  1997. derivative) on a volume of a storage or distribution medium does not bring
  1998. the other program under the scope of these terms.
  1999.  
  2000.   3. You may copy and distribute this program (or a portion or derivative
  2001. of it, under Paragraph 2) in object code or executable form under the terms
  2002. of Paragraphs 1 and 2 above provided that you also do one of the following:
  2003.  
  2004.     a) accompany it with the complete corresponding machine-readable
  2005.     source code, which must be distributed under the terms of
  2006.     Paragraphs 1 and 2 above; or,
  2007.  
  2008.     b) accompany it with a written offer, valid for at least three
  2009.     years, to give any third party free (except for a nominal
  2010.     shipping charge) a complete machine-readable copy of the
  2011.     corresponding source code, to be distributed under the terms of
  2012.     Paragraphs 1 and 2 above; or,
  2013.  
  2014.     c) accompany it with the information you received as to where the
  2015.     corresponding source code may be obtained.  (This alternative is
  2016.     allowed only for noncommercial distribution and only if you
  2017.     received the program in object code or executable form alone.)
  2018.  
  2019. For an executable file, complete source code means all the source code for
  2020. all modules it contains; but, as a special exception, it need not include
  2021. source code for modules which are standard libraries that accompany the
  2022. operating system on which the executable file runs.
  2023.  
  2024.   4. You may not copy, sublicense, distribute or transfer this program
  2025. except as expressly provided under this License Agreement.  Any attempt
  2026. otherwise to copy, sublicense, distribute or transfer this program is void and
  2027. your rights to use the program under this License agreement shall be
  2028. automatically terminated.  However, parties who have received computer
  2029. software programs from you with this License Agreement will not have
  2030. their licenses terminated so long as such parties remain in full compliance.
  2031.  
  2032.   5. If you wish to incorporate parts of this program into other free
  2033. programs whose distribution conditions are different, write to the Free
  2034. Software Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not yet
  2035. worked out a simple rule that can be stated here, but we will often permit
  2036. this.  We will be guided by the two goals of preserving the free status of
  2037. all derivatives of our free software and of promoting the sharing and reuse of
  2038. software.
  2039.  
  2040.  
  2041. In other words, you are welcome to use, share and improve this program.
  2042. You are forbidden to forbid anyone else to use, share and improve
  2043. what you give them.   Help stamp out software-hoarding!  */
  2044.  
  2045.  
  2046. #ifndef RE_NREGS
  2047. #define RE_NREGS 10
  2048. #endif
  2049.  
  2050. /* This data structure is used to represent a compiled pattern. */
  2051.  
  2052. struct re_pattern_buffer
  2053.   {
  2054.     char *buffer;    /* Space holding the compiled pattern commands. */
  2055.     int allocated;    /* Size of space that  buffer  points to */
  2056.     int used;        /* Length of portion of buffer actually occupied */
  2057.     char *fastmap;    /* Pointer to fastmap, if any, or zero if none. */
  2058.             /* re_search uses the fastmap, if there is one,
  2059.                to skip quickly over totally implausible characters */
  2060.     char *translate;    /* Translate table to apply to all characters before comparing.
  2061.                Or zero for no translation.
  2062.                The translation is applied to a pattern when it is compiled
  2063.                and to data when it is matched. */
  2064.     char fastmap_accurate;
  2065.             /* Set to zero when a new pattern is stored,
  2066.                set to one when the fastmap is updated from it. */
  2067.     char can_be_null;   /* Set to one by compiling fastmap
  2068.                if this pattern might match the null string.
  2069.                It does not necessarily match the null string
  2070.                in that case, but if this is zero, it cannot.
  2071.                2 as value means can match null string
  2072.                but at end of range or before a character
  2073.                listed in the fastmap.  */
  2074.   };
  2075.  
  2076. /* Structure to store "register" contents data in.
  2077.  
  2078.    Pass the address of such a structure as an argument to re_match, etc.,
  2079.    if you want this information back.
  2080.  
  2081.    start[i] and end[i] record the string matched by \( ... \) grouping i,
  2082.    for i from 1 to RE_NREGS - 1.
  2083.    start[0] and end[0] record the entire string matched. */
  2084.  
  2085. struct re_registers
  2086.   {
  2087.     int start[RE_NREGS];
  2088.     int end[RE_NREGS];
  2089.   };
  2090.  
  2091. /* These are the command codes that appear in compiled regular expressions, one per byte.
  2092.   Some command codes are followed by argument bytes.
  2093.   A command code can specify any interpretation whatever for its arguments.
  2094.   Zero-bytes may appear in the compiled regular expression. */
  2095.  
  2096. enum regexpcode
  2097.   {
  2098.     unused,
  2099.     exactn,    /* followed by one byte giving n, and then by n literal bytes */
  2100.     begline,   /* fails unless at beginning of line */
  2101.     endline,   /* fails unless at end of line */
  2102.     jump,     /* followed by two bytes giving relative address to jump to */
  2103.     on_failure_jump,     /* followed by two bytes giving relative address of place
  2104.                     to resume at in case of failure. */
  2105.     finalize_jump,     /* Throw away latest failure point and then jump to address. */
  2106.     maybe_finalize_jump, /* Like jump but finalize if safe to do so.
  2107.                 This is used to jump back to the beginning
  2108.                 of a repeat.  If the command that follows
  2109.                 this jump is clearly incompatible with the
  2110.                 one at the beginning of the repeat, such that
  2111.                 we can be sure that there is no use backtracking
  2112.                 out of repetitions already completed,
  2113.                 then we finalize. */
  2114.     dummy_failure_jump,  /* jump, and push a dummy failure point.
  2115.                 This failure point will be thrown away
  2116.                 if an attempt is made to use it for a failure.
  2117.                 A + construct makes this before the first repeat.  */
  2118.     anychar,     /* matches any one character */
  2119.     charset,     /* matches any one char belonging to specified set.
  2120.             First following byte is # bitmap bytes.
  2121.             Then come bytes for a bit-map saying which chars are in.
  2122.             Bits in each byte are ordered low-bit-first.
  2123.             A character is in the set if its bit is 1.
  2124.             A character too large to have a bit in the map
  2125.             is automatically not in the set */
  2126.     charset_not, /* similar but match any character that is NOT one of those specified */
  2127.     start_memory, /* starts remembering the text that is matched
  2128.             and stores it in a memory register.
  2129.             followed by one byte containing the register number.
  2130.             Register numbers must be in the range 0 through NREGS. */
  2131.     stop_memory, /* stops remembering the text that is matched
  2132.             and stores it in a memory register.
  2133.             followed by one byte containing the register number.
  2134.             Register numbers must be in the range 0 through NREGS. */
  2135.     duplicate,    /* match a duplicate of something remembered.
  2136.             Followed by one byte containing the index of the memory register. */
  2137.     before_dot,     /* Succeeds if before dot */
  2138.     at_dot,     /* Succeeds if at dot */
  2139.     after_dot,     /* Succeeds if after dot */
  2140.     begbuf,      /* Succeeds if at beginning of buffer */
  2141.     endbuf,      /* Succeeds if at end of buffer */
  2142.     wordchar,    /* Matches any word-constituent character */
  2143.     notwordchar, /* Matches any char that is not a word-constituent */
  2144.     wordbeg,     /* Succeeds if at word beginning */
  2145.     wordend,     /* Succeeds if at word end */
  2146.     wordbound,   /* Succeeds if at a word boundary */
  2147.     notwordbound, /* Succeeds if not at a word boundary */
  2148.     syntaxspec,  /* Matches any character whose syntax is specified.
  2149.             followed by a byte which contains a syntax code, Sword or such like */
  2150.     notsyntaxspec /* Matches any character whose syntax differs from the specified. */
  2151.   };
  2152.  
  2153. extern char *re_compile_pattern ();
  2154. /* Is this really advertised? */
  2155. extern void re_compile_fastmap ();
  2156. extern int re_search (), re_search_2 ();
  2157. extern int re_match (), re_match_2 ();
  2158.  
  2159. /* 4.2 bsd compatibility (yuck) */
  2160. extern char *re_comp ();
  2161. extern int re_exec ();
  2162.  
  2163. #ifdef SYNTAX_TABLE
  2164. extern char *re_syntax_table;
  2165. #endif
  2166. EOF
  2167. if test `wc -c < regex.h` -ne 10736
  2168. then    echo 'regex.h is the wrong size'
  2169. fi
  2170. echo Archive 3 unpacked
  2171. exit
  2172.  
  2173.